import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.Properties;

import net.Dispatcher;
import net.MessageDispatcher;
import net.Net;
import net.RPC;
import net.VersionChecker;
import rpc.PlayerService;
import system.Config;
import system.G;
import system.L;

import com.mongodb.Mongo;
import com.mongodb.MongoException;

import database.DBMongo;

public class GameServer {

	public PlayerService playerService;
	public Net net;

	public void recoverDB() throws UnknownHostException, MongoException {
		DBMongo db = new DBMongo(new Mongo());
		playerService.recoverFromDB(db);
	}

	public void initGlobal() {
		Dispatcher rd = new Dispatcher();
		G.put("RD", rd);
		MessageDispatcher md = new MessageDispatcher();
		G.put("MD", md);
		net = new Net(Config.SERVER_PORT);
		G.put("Net", net);
		playerService = new PlayerService();
		playerService.init(net.clientBootstrap);
	}

	public void registerHandlers() {
		Dispatcher rd = (Dispatcher) G.get("RD");
		playerService.register(rd);		
		MessageDispatcher md = (MessageDispatcher) G.get("MD");		
		md.register(new RPC(rd, playerService, new VersionChecker()));
	}

	public void config() throws IOException {
		InputStream in = new BufferedInputStream(new FileInputStream(
				"server.properties"));
		Properties p = new Properties();
		p.load(in);
		Config.SERVER_PORT = Short.parseShort(p.getProperty("port"));
		String[] hosts = p.getProperty("server_hosts").split(",");
		Config.SERVER_ADDRS = hosts;
		String[] ports = p.getProperty("server_ports").split(",");
		String[] states = p.getProperty("server_states").split(",");
		Config.SERVER_PORTS = new int[hosts.length];
		Config.SERVER_STATES = new int[hosts.length];
		for (int i = 0; i < hosts.length; i++) {
			Config.SERVER_PORTS[i] = Integer.parseInt(ports[i]);
			Config.SERVER_STATES[i] = Integer.parseInt(states[i]);
		}
		Config.OPEN_VIP = Byte.parseByte(p.getProperty("open_vip"));
		Config.VERIFY_PATH = p.getProperty("verify_path").trim();
		Config.VERIFY_HOST = p.getProperty("verify_host").trim();
		Config.PRODUCT_ID = p.getProperty("pid").trim();
		Config.VERSION = Integer.parseInt(p.getProperty("client_version").trim());		
		Config.APP_91 = Integer.parseInt(p.getProperty("APP_91")) == 1;
		Config.APP_ID_91 = p.getProperty("APP_ID_91").trim();
		Config.APP_KEY_91 = p.getProperty("APP_KEY_91").trim();
		L.config();
		L.debug("debug test");
		L.info("info test");
		L.warn("warn test");
		L.error("error test");
		L.info("server port:" + Config.SERVER_PORT);
		L.info("verify host:" + Config.VERIFY_HOST);
		L.info("verify_path:" + Config.VERIFY_PATH);
		L.info("product id:" + Config.PRODUCT_ID);
		L.info("open vip:" + Config.OPEN_VIP);
		L.info("data version:" + Config.VERSION);
		L.info("app 91:" + Config.APP_91);
		L.info("app id 91:" + Config.APP_ID_91);
		L.info("app key 91:" + Config.APP_KEY_91);
	}

	public void startNet() {
		net.run();
	}

	public void start() {
		try {
			config();
			initGlobal();
			recoverDB();
			registerHandlers();
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
		startNet();
	}

	public static void main(String[] args) {
		new GameServer().start();
		L.debug("free mem " + Runtime.getRuntime().freeMemory());
		L.debug("max mem " + Runtime.getRuntime().maxMemory()); 
		L.debug("total mem " + Runtime.getRuntime().totalMemory());
	}
	
	
}
